﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.UI;
using GrayParrot.Core.FontAwesome;

namespace GrayParrot.Web.Controls
{
    #region Enums...
    /// <summary>
    /// Button types...
    /// </summary>
    public enum ButtonTypes
    {
        [Description("Custom Button")]
        Custom = 0,
        [Description("CRUD Load")]
        CRUDLoad,
        [Description("CRUD Add")]
        CRUDAdd,
        [Description("CRUD Edit")]
        CRUDEdit,
        [Description("CRUD Delete")]
        CRUDDelete,
        //[Description("Download all data")]
        //Download,
        //[Description("Copy all the data to an HTML div")]
        //CopyToDiv
    }

    /// <summary>
    /// Utility Button Types...
    /// </summary>
    public enum UtilityButtonTypes
    {
        [Description("Export To Excel")]
        ExportToExcel,
        [Description("Export To CSV")]
        ExportToCSV,
        [Description("Export To PDF")]
        ExportToPDF,
        [Description("Copy the table to clipboard")]
        Copy,
        [Description("Print the table")]
        Print
    }
    #endregion
    /// <summary>
    /// 
    /// </summary>
    internal class ButtonsComparer : IEqualityComparer<CustomButton>
    {
        /// <summary>
        /// Equalses the specified x.
        /// </summary>
        /// <param name="x">The x.</param>
        /// <param name="y">The y.</param>
        /// <returns></returns>
        public bool Equals(CustomButton x, CustomButton y)
        {
            return x.GetType().Equals(y.GetType()) && (x.GetType().Equals(typeof(CrudAddButton)) ||
                                                       x.GetType().Equals(typeof(CrudDeleteButton)) ||
                                                       x.GetType().Equals(typeof(CrudEditButton)) ||
                                                       x.GetType().Equals(typeof(CrudLoadButton)));
        }

        /// <summary>
        /// Returns a hash code for this instance.
        /// </summary>
        /// <param name="obj">The obj.</param>
        /// <returns>
        /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. 
        /// </returns>
        public int GetHashCode(CustomButton obj)
        {
            return obj.GetType().GetHashCode();
        }
    }

    [Serializable]
    public class Toolbar : List<IconButton>
    { 
    }

    [Serializable]
    public class IconButton 
    {
        public string Icon { get; set; }
        /// <summary>
        /// Gets or sets the callback.
        /// </summary>
        /// <value>
        /// The callback.
        /// </value>
        public string Callback { get; set; }
        /// <summary>
        /// Gets or sets the parameters values for the callback associated to the custom button...
        /// </summary>
        /// <value>
        /// The parameters.
        /// </value>
        public List<ButtonCallbackParameter> Parameters { get; set; }

        public IconButton()
        {
        }
    }

    /// <summary>
    /// 
    /// </summary>
    [Serializable]
    public class Buttons : List<CustomButton>
    {
        IEqualityComparer<CustomButton> customComparer = null;

        /// <summary>
        /// Initializes a new instance of the <see cref="Buttons"/> class.
        /// </summary>
        public Buttons()
        {
            customComparer = new ButtonsComparer();
        }

        /// <summary>
        /// Adds the specified item.
        /// </summary>
        /// <param name="item">The item.</param>
        /// <exception cref="System.Exception"></exception>
        public new void Add(CustomButton item)
        {
            if (!this.Contains(item, customComparer))
            {
                base.Add(item);
            }
            else
            {
                throw new Exception(string.Format("Errore Pulsante duplicato \"{0}\", \"{1}\": Tipo di pulsante già presente !", item.Text, item.Type));
            }
        }
    }

    /// <summary>
    /// 
    /// </summary>
    public interface IBaseButton
    {
        /// <summary>
        /// Gets or sets the text.
        /// </summary>
        /// <value>
        /// The text.
        /// </value>
        string Text { get; set; }
        /// <summary>
        /// Gets or sets the type.
        /// </summary>
        /// <value>
        /// The type.
        /// </value>
        ButtonTypes Type { get; set; }
        /// <summary>
        /// Gets or sets the callback.
        /// </summary>
        /// <value>
        /// The callback.
        /// </value>
        string Callback { get; set; }
        /// <summary>
        /// Gets or sets the parameters values for the callback associated to the custom button...
        /// </summary>
        /// <value>
        /// The parameters.
        /// </value>
        List<ButtonCallbackParameter> Parameters { get; set; }
    }

    /// <summary>
    /// Buttons base class...
    /// </summary>
    [TypeConverter(typeof(ExpandableObjectConverter))]
    public abstract class ButtonBase : IBaseButton
    {
        /// <summary>
        /// Gets or sets the text.
        /// </summary>
        /// <value>
        /// The text.
        /// </value>
        public string Text { get; set; }
        /// <summary>
        /// Gets or sets the type.
        /// </summary>
        /// <value>
        /// The type.
        /// </value>
        public ButtonTypes Type { get; set; }
        /// <summary>
        /// Gets or sets the callback.
        /// </summary>
        /// <value>
        /// The callback.
        /// </value>
        public abstract string Callback { get; set; }

        /// <summary>
        /// Gets or sets the parameters values for the callback associated to the custom button...
        /// </summary>
        /// <value>
        /// The parameters.
        /// </value>
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content), PersistenceMode(PersistenceMode.InnerProperty)]
        public abstract List<ButtonCallbackParameter> Parameters { get; set; }
    }

    /// <summary>
    /// Custom Button class...
    /// </summary>
    [TypeConverter(typeof(ExpandableObjectConverter))]
    public class CustomButton : ButtonBase
    {
        /// <summary>
        /// Gets or sets the callback.
        /// </summary>
        /// <value>
        /// The callback.
        /// </value>
        public override string Callback { get; set; }

        /// <summary>
        /// Gets or sets the type.
        /// </summary>
        /// <value>
        /// The type.
        /// </value>
        public new ButtonTypes Type { get; internal set; }

        /// <summary>
        /// Gets or sets the parameters values for the callback associated to the custom button...
        /// </summary>
        /// <value>
        /// The parameters.
        /// </value>
        public override List<ButtonCallbackParameter> Parameters { get; set; }

        /// <summary>
        /// Initializes a new instance of the <see cref="CustomButton"/> class.
        /// </summary>
        public CustomButton()
        {
            this.Type = ButtonTypes.Custom;
        }
    }

    ///// <summary>
    ///// Download Button..
    ///// </summary>
    //[TypeConverter(typeof(ExpandableObjectConverter))]
    //public class DownloadButton : CustomButton
    //{
    //    /// <summary>
    //    /// Gets or sets the URL.
    //    /// </summary>
    //    /// <value>
    //    /// The URL.
    //    /// </value>
    //    public string Url { get; set; }

    //    /// <summary>
    //    /// Gets or sets the callback.
    //    /// </summary>
    //    /// <value>
    //    /// The callback.
    //    /// </value>
    //    //internal new string Callback { get; set; }

    //    /// <summary>
    //    /// Initializes a new instance of the <see cref="CrudLoadButton"/> class.
    //    /// </summary>
    //    public DownloadButton()
    //    {
    //        this.Type = ButtonTypes.Download;
    //        this.Text = "Load";
    //    }
    //}

    /// <summary>
    /// Copy to Div Button...
    /// </summary>
    //[TypeConverter(typeof(ExpandableObjectConverter))]
    //public class CopyToDivButton : CustomButton
    //{
    //    /// <summary>
    //    /// Gets or sets the URL.
    //    /// </summary>
    //    /// <value>
    //    /// The URL.
    //    /// </value>
    //    public string Url { get; set; }

    //    /// <summary>
    //    /// Gets or sets the callback.
    //    /// </summary>
    //    /// <value>
    //    /// The callback.
    //    /// </value>
    //    //internal new string Callback { get; set; }

    //    /// <summary>
    //    /// Initializes a new instance of the <see cref="CrudLoadButton"/> class.
    //    /// </summary>
    //    public CopyToDivButton()
    //    {
    //        this.Type = ButtonTypes.CopyToDiv;
    //        this.Text = "Load";
    //    }
    //}

    /// <summary>
    /// 
    /// </summary>
    [TypeConverter(typeof(ExpandableObjectConverter))]
    public class CrudLoadButton : CustomButton
    {
        /// <summary>
        /// Gets or sets the URL.
        /// </summary>
        /// <value>
        /// The URL.
        /// </value>
        public string Url { get; set; }

        /// <summary>
        /// Gets or sets the callback.
        /// </summary>
        /// <value>
        /// The callback.
        /// </value>
        //internal new string Callback { get; set; }

        /// <summary>
        /// Initializes a new instance of the <see cref="CrudLoadButton"/> class.
        /// </summary>
        public CrudLoadButton()
        {
            this.Type = ButtonTypes.CRUDLoad;
            this.Text = "Load";
        }
    }

    /// <summary>
    /// 
    /// </summary>
    [TypeConverter(typeof(ExpandableObjectConverter))]
    public class CrudAddButton : CustomButton
    {
        /// <summary>
        /// Gets or sets the template.
        /// </summary>
        /// <value>
        /// The template.
        /// </value>
        public string Template { get; set; }

        /// <summary>
        /// Gets or sets the URL.
        /// </summary>
        /// <value>
        /// The URL.
        /// </value>
        public string Url { get; set; }
        /// <summary>
        /// Gets or sets the callback.
        /// </summary>
        /// <value>
        /// The callback.
        /// </value>
        //internal new string Callback { get; set; }

        /// <summary>
        /// Initializes a new instance of the <see cref="CrudAddButton"/> class.
        /// </summary>
        public CrudAddButton()
        {
            this.Type = ButtonTypes.CRUDAdd;
            this.Text = "New";
            this.Template = string.Empty;
        }
    }

    /// <summary>
    /// 
    /// </summary>
    [TypeConverter(typeof(ExpandableObjectConverter))]
    public class CrudEditButton : CustomButton
    {
        /// <summary>
        /// Gets or sets the URL.
        /// </summary>
        /// <value>
        /// The URL.
        /// </value>
        public string Url { get; set; }
        /// <summary>
        /// Gets or sets the callback.
        /// </summary>
        /// <value>
        /// The callback.
        /// </value>
        //internal new string Callback { get; set; }

        /// <summary>
        /// Initializes a new instance of the <see cref="CrudEditButton"/> class.
        /// </summary>
        public CrudEditButton()
        {
            this.Type = ButtonTypes.CRUDEdit;
            this.Text = "Edit";
        }
    }

    /// <summary>
    /// 
    /// </summary>
    [TypeConverter(typeof(ExpandableObjectConverter))]
    public class CrudDeleteButton : CustomButton
    {
        /// <summary>
        /// Gets or sets the URL.
        /// </summary>
        /// <value>
        /// The URL.
        /// </value>
        public string Url { get; set; }
        /// <summary>
        /// Gets or sets the callback.
        /// </summary>
        /// <value>
        /// The callback.
        /// </value>
        //internal new string Callback { get; set; }

        /// <summary>
        /// Initializes a new instance of the <see cref="CrudDeleteButton"/> class.
        /// </summary>
        public CrudDeleteButton()
        {
            this.Type = ButtonTypes.CRUDDelete;
            this.Text = "Delete";
        }
    }

    /// <summary>
    /// 
    /// </summary>
    [TypeConverter(typeof(ExpandableObjectConverter))]
    public class UtilityButton : CustomButton
    {
        /// <summary>
        /// Gets or sets the title of the exported file...
        /// </summary>
        /// <value>
        /// The title.
        /// </value>
        public string Title { get; set; }
        /// <summary>
        /// Gets or sets the type.
        /// </summary>
        /// <value>
        /// The type.
        /// </value>
        public new UtilityButtonTypes Type { get; set; }
        /// <summary>
        /// Gets or sets the callback.
        /// </summary>
        /// <value>
        /// The callback.
        /// </value>
        internal new string Callback { get; set; }
        /// <summary>
        /// Initializes a new instance of the <see cref="UtilityButton"/> class.
        /// </summary>
        public UtilityButton()
        {
        }

        /// <summary>
        /// Gets the utility button code...
        /// </summary>
        /// <param name="type">The type.</param>
        /// <returns></returns>
        public string GetCode()
        {
            string retValue = string.Empty;

            switch (this.Type)
            {
                case UtilityButtonTypes.ExportToExcel:
                    retValue = "excel";
                    break;
                case UtilityButtonTypes.ExportToCSV:
                    retValue = "csv";
                    break;
                case UtilityButtonTypes.ExportToPDF:
                    retValue = "pdf";
                    break;
                case UtilityButtonTypes.Copy:
                    retValue = "copy";
                    break;
                case UtilityButtonTypes.Print:
                    retValue = "print";
                    break;
                default:
                    break;
            }

            return retValue;
        }
    }
}
